/*
 * Copyright (c) 2012 RTCLab
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are
 * permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
 *    of conditions and the following disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 */

package com.rtckit {

import flash.net.*;
import flash.events.*;
import flash.media.*;

public class OutgoingMedia extends Media {
	private var video:Boolean = false;
	private var audioCodec:String = "";
	private var micEnabled:Boolean = false;

	function OutgoingMedia(nc:NetConnection, config:SoftphoneConfig) {
		super(nc, config);
		
		config.reportMicChanged = reportMicChanged;

		serverStream = createStream();
		
		peerStream = createStream(NetStream.DIRECT_CONNECTIONS);
		peerStream.publish("P2P" + nc.nearID);
	}
	
	public function createStream(peerID:String = NetStream.CONNECT_TO_FMS):NetStream {
		var stream:NetStream = new NetStream(nc, peerID);
		stream.addEventListener(NetStatusEvent.NET_STATUS, this.netStatusHandler, false, 0, true);
		stream.addEventListener(IOErrorEvent.IO_ERROR, this.streamErrorHandler, false, 0, true);
		stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, this.streamErrorHandler, false, 0, true);
		stream.audioReliable = false;
		stream.client = this;
		return stream;
	}
	
	public function attachAudio(stream:NetStream):void {
		if (config.mic) {
			config.mic.codec = this.audioCodec;
			config.mic.enableVAD = true;
			config.mic.setSilenceLevel(0);
			config.mic.encodeQuality = 10;
			config.mic.framesPerPacket = this.audioCodec == "Speex" ? 1 : 2;
			config.mic.setUseEchoSuppression(true);
			stream.attachAudio(config.mic);
			micEnabled = true;
		}
	}
	
	public function detachAudio(stream:NetStream):void {
		stream.attachAudio(null);
		micEnabled = false;
	}
	
	public function reportMicChanged():void {
		if (!micEnabled)
			return;
		var stream:NetStream = currentStream();
		detachAudio(stream);
		attachAudio(stream);
	}
	
	override public function currentStream():NetStream {
		return serverStream ? serverStream : peerStream;
	}
	
	public function attachVideo(stream:NetStream):void {
		CONFIG::FP_11 {
			var h264Settings:H264VideoStreamSettings = new H264VideoStreamSettings();
			h264Settings.setProfileLevel(H264Profile.BASELINE, H264Level.LEVEL_2);
			stream.videoStreamSettings = h264Settings;
		}
		
		stream.videoReliable = false;
		stream.bufferTime = 0;
		var cam:Camera = Camera.getCamera();
		if (!cam) {
			Logger.error('Camera is not available');
			return;
		}
		
		cam.setMode(352, 288, 15);
		
		if (!CONFIG::FP_11)
			cam.setQuality(33000, 0);
		
		stream.attachCamera(cam);
	}
	
	public function publishServerStream():void {
		detachAudio(peerStream);
		peerStream.attachCamera(null);
		
		serverStream = createStream();
		attachAudio(serverStream);
		if (video)
			attachVideo(serverStream);
		serverStream.publish(nc.nearID);
	}
	
	public function connect(name:String, hasVideo:Boolean, audioCodec:String, peerID:String):void {
		video = hasVideo && config.videoContainer;
		this.audioCodec = audioCodec ? audioCodec : "Speex";

		if (peerID) {
			attachAudio(peerStream);
			if (video)
				attachVideo(peerStream);
		} else {
			publishServerStream();
		}
		
		waitPeerConnection(peerID);
	}
	
	override public function onPeerConnectionFailed():void {
		publishServerStream();
	}
	
	public function disconnect():void {
		if (serverStream) {
			detachAudio(serverStream);
			serverStream.close();
			serverStream = null;
		}
		detachAudio(peerStream);
		peerStream.attachCamera(null);
	}
	
	public function destroy():void {
		peerStream.close();
	}
	
	private function netStatusHandler(event:NetStatusEvent):void {
		var target:String = event.target == peerStream ? "P2P out" : "out";
		Logger.debug(target + ": " + event.info.code);
	}
	
	private function streamErrorHandler(event:ErrorEvent):void {
		var target:String = event.target == peerStream ? "P2P out" : "out";
		Logger.debug(target + ": " + event.type + ' ' + event.text);
	}
}

}
